﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using IQReportes.Utils;
using System.Data.SqlClient;
using System.Data;


namespace IQReportes.Models.Logica
{
    public class LogicaCargaCSV
    {
        private Dictionary<string, DIR> diccionarioDIR = new Dictionary<string, DIR>();
        private Dictionary<string, int> diccionarioTipos = new Dictionary<string, int>();
        private Dictionary<string, int> diccionarioEstados = new Dictionary<string, int>();
        private DateTime fechaBase;
        
        private EstadoTransaccionDAO dbEstadoTxn = new EstadoTransaccionDAO();
        private TipoTransaccionDAO dbTiposTxn = new TipoTransaccionDAO();
        private DirDAO dbDIR = new DirDAO();
        private FechaCSVDAO dbFecha = new FechaCSVDAO();
        private ConexionSQL dbSQL = new ConexionSQL();


        public bool existeFechaCSV(string stFecha, int codInstitucion)
        {
            try
            {
                var fechas = dbFecha.dbFechas.Where(a => a.vcFecha == stFecha && a.inCodInstitucion == codInstitucion);
                if (fechas.Count() > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch(Exception e)
            {
                string gg = e.Message;
                return true;
            }
        }

        private void cargarDatosIniciales()
        {
            try
            {
                var listaTiposTxn = dbTiposTxn.tiposTransaccion;
                var listaEstadosTxn = dbEstadoTxn.estados;
                var listaDIR = dbDIR.dirs;
                

                foreach (var t in listaTiposTxn)
                {
                    diccionarioTipos.Add(t.vcNombre, t.idTipo);
                }

                foreach (var e in listaEstadosTxn)
                {
                    diccionarioEstados.Add(e.vcNombre, e.idEstado);
                }

                foreach (var d in listaDIR)
                {
                    diccionarioDIR.Add(d.vcCodDIR, d);
                }
                fechaBase = DateTime.Now.AddDays(-1);
            }
            catch (Exception e)
            {
                string gg = e.Message;
            }
        }

        public bool cargarTransaccionesCsv(string path, string nombreArch, int confirmacion, List<string> dirsConError,
                                            DateTime fecha)
        {
            List<ConsolidadoTransaccion> listaConsolidado = new List<ConsolidadoTransaccion>();
            List<DIR> listaDIRs = new List<DIR>();
            ConsolidadoTransaccion consActual;
            dirsConError = new List<string>();
            try
            {
                cargarDatosIniciales();
                path = path + "\\" + nombreArch;
                string[] csvData = File.ReadAllLines(path);
                var transacciones = (from i in csvData
                                     let rowData = i.Split(',') //splits each row into an array called rowData
                                     select new Transaccion
                                     {
                                         vcHora = rowData[0],
                                         vcNemonico = rowData[1],
                                         vcDIR = rowData[2],
                                         vcEstado = rowData[3],
                                         vcNombreTransaccion = rowData[4],
                                         dbMonto = Double.Parse(rowData[11]),
                                         inMoneda = Int32.Parse(rowData[12])
                                     }).ToList();

                var gg = transacciones.AsQueryable().GroupBy(a =>
                    new
                    {
                        a.vcNombreTransaccion,
                        a.vcEstado,
                        a.vcDIR
                    }).Select(a => new ConsolidadoTransaccion
                    {
                        tipoTransaccion = a.Key.vcNombreTransaccion,
                        estadoTransaccion = a.Key.vcEstado,
                        codDIR = a.Key.vcDIR,
                        cantidadTransacciones = a.Count(),
                        monto = a.Sum(x => x.dbMonto)
                    });

                foreach (var item in gg)
                {
                    if (diccionarioDIR.ContainsKey(item.codDIR))
                    {
                        consActual = item;
                        listaDIRs.Add(diccionarioDIR[item.codDIR]); //ESTO VA SERVIR PARA EL PROCESO BATCH CUANDO SE ACTUALICE
                        //LOS DIRS MEDIANTE WEB SERVICES
                        if (diccionarioTipos.ContainsKey(item.tipoTransaccion))
                        {
                            item.idTipoTransaccion = diccionarioTipos[item.tipoTransaccion];
                        }
                        if (diccionarioEstados.ContainsKey(item.estadoTransaccion))
                        {
                            item.idEstadoTransaccion = diccionarioEstados[item.estadoTransaccion];
                        }
                        if (item.idTipoTransaccion != null && item.idTipoTransaccion != 0
                            && item.idEstadoTransaccion != null && item.idEstadoTransaccion != 0)
                        {
                            listaConsolidado.Add(item);
                        }
                    }
                    else
                    {
                        dirsConError.Add(item.codDIR);
                    }
                }
                
                if (confirmacion == Constantes.CONFIRMACION_OK)
                {
                    DateTime antes, despues;
                    antes = DateTime.Now;
                    //DateTime fecha = DateTime.Now.AddDays(-4);
                    cargarDatosTransacciones(listaConsolidado, fecha, Constantes.CODIGO_IBK);
                    despues = DateTime.Now;
                    TimeSpan intervalo;
                    intervalo = despues.Subtract(antes);
                    int kk = intervalo.Minutes;
                }
                return true;
                
            }
            catch (Exception e)
            {
                string ff = e.Message;
                return false;
            }

        }
        private void cargarDatosTransacciones(List<ConsolidadoTransaccion> listaConsolidado, DateTime fecha, int institucion)
        {
            foreach (ConsolidadoTransaccion c in listaConsolidado)
            {
                actualizaConsolidados(c.codDIR, c.idEstadoTransaccion, c.idTipoTransaccion, c.cantidadTransacciones, c.monto, fecha, institucion);
            }
        }

        private void actualizaConsolidados(string dir, int idEstado, int idTipoTxn, int cantTxn, double monto, DateTime fecha, int institucion)
        {
            //calcular antiguedadPeriodo
            int antiguedadMes = calcularAntiguedadxPeriodo(Constantes.TBL_CONS_MES, fecha);
            int antiguedadSemana = calcularAntiguedadxPeriodo(Constantes.TBL_CONS_SEMANA, fecha); ;
            int antiguedadDia = calcularAntiguedadxPeriodo(Constantes.TBL_CONS_DIA, fecha);
            int ano = fecha.Year;


            actualizarConsolidadoStoredProd(dir, idEstado, idTipoTxn, cantTxn, monto, Constantes.TBL_CONS_ANO, ano, institucion);

            if (antiguedadMes != -1)
            {
                actualizarConsolidadoStoredProd(dir, idEstado, idTipoTxn, cantTxn, monto, Constantes.TBL_CONS_MES, antiguedadMes, institucion);
            }
            if (antiguedadSemana != -1)
            {
                actualizarConsolidadoStoredProd(dir, idEstado, idTipoTxn, cantTxn, monto, Constantes.TBL_CONS_SEMANA, antiguedadSemana, institucion);
            }
            if (antiguedadDia != -1)
            {
                actualizarConsolidadoStoredProd(dir, idEstado, idTipoTxn, cantTxn, monto, Constantes.TBL_CONS_DIA, antiguedadDia, institucion);
            }
        }

        private void actualizarConsolidadoStoredProd(string codDir, int idEstado, int idTipoTxn, int cantTxn,
                                            double monto, string nombreTabla, int antiguedadPeriodo, int institucion)
        {
            string nombreStored = "";
            List<SqlParameter> listaParametros = new List<SqlParameter>();
            int codigoTabla = calcularCodigoTabla(nombreTabla);
            switch (codigoTabla)
            {
                case 1:
                    nombreStored = ProcedimientosAlmacenados.actualiza_consolidado_dia;
                    break;
                case 2:
                    nombreStored = ProcedimientosAlmacenados.actualiza_consolidado_semana;
                    break;
                case 3:
                    nombreStored = ProcedimientosAlmacenados.actualiza_consolidado_mes;
                    break;
                case 4:
                    nombreStored = ProcedimientosAlmacenados.actualiza_consolidado_ano;
                    break;
            }

            SqlParameter param1 = new SqlParameter("@idEstado", SqlDbType.Int);
            SqlParameter param2 = new SqlParameter("@idTipo", SqlDbType.Int);
            SqlParameter param3 = new SqlParameter("@codDir", SqlDbType.VarChar, 30);
            SqlParameter param4 = new SqlParameter("@cantTxn", SqlDbType.Int);
            SqlParameter param5 = new SqlParameter("@monto", SqlDbType.Float);
            SqlParameter param6 = new SqlParameter("@codTabla", SqlDbType.Int);
            SqlParameter param7 = new SqlParameter("@antiguedadPeriodo", SqlDbType.Int);
            SqlParameter param8 = new SqlParameter("@institucion", SqlDbType.Int);

            param1.Value = idEstado;
            param2.Value = idTipoTxn;
            param3.Value = codDir;
            param4.Value = cantTxn;
            param5.Value = monto;
            param6.Value = codigoTabla;
            param7.Value = antiguedadPeriodo;
            param8.Value = institucion;

            listaParametros.Add(param1);
            listaParametros.Add(param2);
            listaParametros.Add(param3);
            listaParametros.Add(param4);
            listaParametros.Add(param5);
            listaParametros.Add(param6);
            listaParametros.Add(param7);
            listaParametros.Add(param8);

            dbSQL.ejecturarNoReaderProcedure(listaParametros, nombreStored);
        }

        private int calcularCodigoTabla(string nombreTabla)
        {
            if (Constantes.TBL_CONS_ANO.Equals(nombreTabla))
            {
                return Constantes.CODIGO_ANO;
            }
            else if (Constantes.TBL_CONS_MES.Equals(nombreTabla))
            {
                return Constantes.CODIGO_MES;
            }
            else if (Constantes.TBL_CONS_SEMANA.Equals(nombreTabla))
            {
                return Constantes.CODIGO_SEMANA;
            }
            else
            {
                return Constantes.CODIGO_DIA;
            }
        }

        private int calcularAntiguedadxPeriodo(string nombreTabla, DateTime fechaRecibida)
        {
            int antiguedad = -1;
            TimeSpan intervalo;
            fechaBase = (new LogicaParametro()).getFechaFinalTx();
            intervalo = fechaBase.Subtract(fechaRecibida);
            //SE ASUME QUE LA FECHA RECIBIDA SIEMPRE VA A SER MENOR QUE LA FECHA BASE
            if (Constantes.TBL_CONS_MES.Equals(nombreTabla))
            {
                if (fechaRecibida.Year == fechaBase.Year)
                {
                    antiguedad = fechaBase.Month - fechaRecibida.Month;
                }
                else
                {
                    antiguedad = 12 - fechaRecibida.Month + fechaBase.Month;
                }
                if (antiguedad > 11) { antiguedad = -1; }
            }
            if (Constantes.TBL_CONS_SEMANA.Equals(nombreTabla))
            {
                antiguedad = intervalo.Days / 7;
                if (antiguedad > 6) { antiguedad = -1; }
            }
            if (Constantes.TBL_CONS_DIA.Equals(nombreTabla))
            {
                antiguedad = intervalo.Days;
                if (antiguedad > 6) { antiguedad = -1; }
            }

            return antiguedad;
        }
    }
}